
import { EnumBetResult, EnumBjlResult } from "@/models/enums/EnumBjlResult";
import { IPlan } from "./IExecutePlan";
import { IRecmStrategy } from "./IRecmStrategy";
import { IMoneyStrategy } from "./IMoneyStrategy";
import { ICopy } from "./ICopy";

export type ExcutePlanOption =
    {
        id?: string,
        planName?: string,
        userInput?: boolean,
        recmStrategy?: IRecmStrategy[],
        moneyStrategy?: IMoneyStrategy[]
    };

/**
 * 计划
 */
export class ExcutePlan implements IPlan {
    recmInfo: RecmInfo = new RecmInfo();
    userRecmInfo: RecmInfo = new RecmInfo();
    multiple: number;
    originMultiple: number = 0;
    waterRate: number;
    fuliRate: number;
    baseMoney: number;
    strategyName: string = '';
    relationPindex: number[] | null = null;
    running: boolean = true;
    resetMoney?: number = 0;
    bflag: boolean = false;
    constructor(option?: ExcutePlanOption) {
        this.resetStrategy();
        this.multiple = 1;
        this.waterRate = 0.05;
        this.fuliRate = 0.01;
        this.baseMoney = 100;
        if (option) {
            this.id = option.id ?? "";
            this.planName = option.planName ?? "";
            if (option.recmStrategy && option.recmStrategy.length > 0) {
                this.recmStrategy = option.recmStrategy;
            }
            if (option.moneyStrategy && option.moneyStrategy.length > 0) {
                this.moneyStrategy = option.moneyStrategy;
            }
        }

    }
    resetRecm(): void {
        this.recmInfo.recmV = EnumBjlResult.U;
        this.userRecmInfo.recmV = EnumBjlResult.U;
        this.recmStrategy.forEach(pl => pl.resetRecm());
        this.moneyStrategy.forEach(st => st.resetRecm());
    }
    resetStrategy(): void {
        this.recmInfo = new RecmInfo();
        this.userRecmInfo = new RecmInfo();
        this.multiple = this.originMultiple;
        this.moneyStrategy.forEach(it => it.resetStrategy());
    }
    copyValue(valueObj: any): void {
        let plan = valueObj as ExcutePlan;
        if (plan) {
            this.baseMoney = plan.baseMoney;
            this.debugCompoenent = plan.debugCompoenent;
            this.fuliRate = plan.fuliRate;
            this.id = plan.id;
            this.multiple = plan.multiple;
            this.running = plan.running;
            this.waterRate = plan.waterRate;
            this.planName = plan.planName;
            this.resetMoney = plan.resetMoney;
            this.bflag = plan.bflag;
            this.originMultiple = plan.originMultiple;

            this.recmInfo.copyValue(plan.recmInfo);
            this.userRecmInfo.copyValue(plan.userRecmInfo);
            //this.recmStrategy.splice(0,this.recmStrategy.length);
            for (let i = 0; i < this.recmStrategy.length; i++) {
                this.recmStrategy[i].copyValue(plan.recmStrategy[i]);
            }

            for (let i = 0; i < this.moneyStrategy.length; i++) {
                this.moneyStrategy[i].copyValue(plan.moneyStrategy[i]);
            }
            // if (this.resetSummaryInfo && plan.resetSummaryInfo) {
            //     this.resetSummaryInfo?.copyValue(plan.resetSummaryInfo);
            // }

            if (this.resetSummaryInfo && plan.resetSummaryInfo) {
                this.resetSummaryInfo.copyValue(plan.resetSummaryInfo);
            }
            else if (this.resetSummaryInfo == null) {
                this.resetSummaryInfo = plan.resetSummaryInfo;
            }
            else {
                this.resetSummaryInfo = null;
            }


        }
    }
    debugCompoenent: string = "";
    /**
     * 计划id
     */
    id: string = "";
    /**
     * 计划名称
     */
    planName: string = "";
    /**
     * 方向推荐策略
     */
    recmStrategy: IRecmStrategy[] = [];
    /**
     * 金额推荐策略
     */
    moneyStrategy: IMoneyStrategy[] = [];
    /**
     * 
     * @param roundInfo 
     * @param recmInfo 
     * @param multiple 
     */
    setResult(roundInfo: RoundInfo, recmInfo: RecmInfo, multiple: number, waterRate: number, fuliRate: number): void {
        let recmMoney = this.recmInfo.recmMoney;
        if (this.multiple > 0) {
            recmMoney = recmMoney * this.multiple;
        }
        this.recmInfo.summaryInfo.updateSummaryInfo(roundInfo.currentResult, this.recmInfo.recmV, recmMoney, this.waterRate, this.fuliRate);
        this.recmInfo.roundSummaryInfo.updateSummaryInfo(roundInfo.currentResult, this.recmInfo.recmV, recmMoney, this.waterRate, this.fuliRate);

        this.userRecmInfo.summaryInfo.updateSummaryInfo(roundInfo.currentResult, this.userRecmInfo.recmV, recmMoney, this.waterRate, this.fuliRate);
        this.userRecmInfo.roundSummaryInfo.updateSummaryInfo(roundInfo.currentResult, this.userRecmInfo.recmV, recmMoney, this.waterRate, this.fuliRate);

        this.recmStrategy.forEach(strategy => strategy.setResult(roundInfo, this.recmInfo, this.multiple, this.waterRate, this.fuliRate));
    }
    /**
     * 计算本地投注方向
     * @param roundInfo 信息
     */
    toResult(roundInfo: RoundInfo): EnumBjlResult {
        let zc = 0;
        let xc = 0;
        for (let i = 0; i < this.recmStrategy.length; i++) {
            let recm = this.recmStrategy[i];
            let v = recm.toResult(roundInfo);
            if (v == EnumBjlResult.Z) {
                zc++;
            }
            else if (v == EnumBjlResult.X) {
                xc++;
            }
        }
        if (zc > xc) {
            return EnumBjlResult.Z;
        }
        else if (xc > zc) {
            return EnumBjlResult.X;
        }
        return EnumBjlResult.U;
    }
    /**
     * 
     * @param roundInfo 
     * @param recmInfo 
     * @param userRecm 
     * @param baseMoney 
     * @returns 
     */
    toMoney(roundInfo: RoundInfo, recmInfo?: RecmInfo, userRecm?: RecmInfo, baseMoney?: number): [EnumBjlResult, number] {
        let zm = 0;
        let xm = 0;
        let recmMoney = 0;
        let recmV = EnumBjlResult.U;
        for (let i = 0; i < this.moneyStrategy.length; i++) {
            let moneyStrategy = this.moneyStrategy[i]
            let [rv, rcmoney] = moneyStrategy.toMoney(roundInfo, recmInfo ?? this.recmInfo, userRecm ?? this.userRecmInfo, baseMoney ?? this.baseMoney);
            if (rv == EnumBjlResult.Z) {
                zm += rcmoney;
            }
            else if (rv == EnumBjlResult.X) {
                xm += rcmoney;
            }
        }
        if (zm > xm) {
            //return [EnumBjlResult.Z, zm - xm];
            recmV = EnumBjlResult.Z;
            recmMoney = zm - xm;
        }
        else if (xm > zm) {
            //return [EnumBjlResult.X, xm - zm];
            recmV = EnumBjlResult.X;
            recmMoney = xm - zm;
        }
        else {
            recmV = EnumBjlResult.U;
        }
        return [recmV, recmMoney];
    }
    showMoney(roundInfo?: RoundInfo): [EnumBjlResult, number] {
        let zm = 0;
        let xm = 0;
        let recmMoney = 0;
        let recmV = EnumBjlResult.U;
        for (let i = 0; i < this.moneyStrategy.length; i++) {
            let moneyStrategy = this.moneyStrategy[i]
            let [rv, rcmoney] = moneyStrategy.showMoney(roundInfo);
            if (rv == EnumBjlResult.Z) {
                zm += rcmoney;
            }
            else if (rv == EnumBjlResult.X) {
                xm += rcmoney;
            }
        }
        if (zm > xm) {
            recmV = EnumBjlResult.Z;
            recmMoney = zm - xm;
        }
        else if (xm > zm) {
            recmV = EnumBjlResult.X;
            recmMoney = xm - zm;
        }
        else {
            recmV = EnumBjlResult.U;
        }
        return [recmV, recmMoney];
    }
    //prevRecm: RecmInfo | null = null;
    resetSummaryInfo: SummaryInfo | null = null;
    resetPlan() {
        if (this.resetSummaryInfo) {
            this.resetSummaryInfo.addSummaryInfo(this.recmInfo.summaryInfo);
        }
        else {
            this.resetSummaryInfo = this.recmInfo.summaryInfo;
        }
        this.recmInfo = new RecmInfo();
        this.userRecmInfo = new RecmInfo();
        this.recmStrategy.forEach(item => item.resetRecm());
        this.moneyStrategy.forEach(item => item.resetStrategy());
        this.running = true;
        this.bflag = false;
    }
    resetPlanSummaryInfo() {
        this.recmInfo.summaryInfo.resetSummaryInfo();
        this.recmInfo.roundSummaryInfo.resetSummaryInfo();
        this.userRecmInfo.summaryInfo.resetSummaryInfo();
        this.userRecmInfo.roundSummaryInfo.resetSummaryInfo();
    }
}

/**
 * 轮次信息
 */
export class RoundInfo implements ICopy {
    copyValue(valueObj: any): void {
        let obj = valueObj as RoundInfo;
        if (obj) {
            this.currentResult = obj.currentResult;
            this.results = obj.results;
            this.userRecm = obj.userRecm;
            this.changeCount = obj.changeCount;
            this.prevRestNum = obj.prevRestNum;
            this.betResultArray = obj.betResultArray;
        }
    }
    /**
     * 当前所有结果
     */
    results: Array<EnumBjlResult> = [];
    /**
     * 当前结果
     */
    currentResult: EnumBjlResult = EnumBjlResult.U;

    userRecm: EnumBjlResult = EnumBjlResult.U;
    changeCount: number = 0;
    /**
     * 神预测结果
     */
    userResult: EnumBetResult = EnumBetResult.NotBet;

    /**
     * 真实推荐结果
     */
    recmResult: EnumBetResult = EnumBetResult.NotBet;

    prevRestNum: number = 0;

    betResultArray: EnumBetResult[] = [];
    reverse: boolean = false;
}

export class SummaryInfo implements ICopy {
    copyValue(valueObj: any): void {
        let obj = valueObj as SummaryInfo;
        if (obj) {
            this.prevResult = obj.prevResult;
            this.zCount = obj.zCount;
            this.xCount = obj.xCount;
            this.winCount = obj.winCount;
            this.failCount = obj.failCount;
            this.winMoney = obj.winMoney;
            this.failMoney = obj.failMoney;
            this.waterMoney = obj.waterMoney;
            this.fuliMoney = obj.fuliMoney;
            this.lwin = obj.lwin;
            this.lfail = obj.lfail;
            this.recmResults.splice(0, this.recmResults.length, ...obj.recmResults);

            this.stWin = obj.stWin;
        }

    }
    prevResult: EnumBetResult = EnumBetResult.NotBet;
    recmResults: EnumBetResult[] = [];
    zCount: number = 0;
    xCount: number = 0;
    winCount: number = 0;
    failCount: number = 0;
    winMoney: number = 0;
    failMoney: number = 0;
    waterMoney: number = 0;
    fuliMoney: number = 0;
    lwin: number = 0;
    lfail: number = 0;

    stWin: number = 0;
    /**
     * 
     * @param result 结果
     * @param recmV 推荐值
     * @param recmMoney  推荐金额
     * @param waterRate  抽水比例
     * @param fuliRate  福利比例
     */
    updateSummaryInfo(result: EnumBjlResult, recmV: EnumBjlResult, recmMoney: number, waterRate?: number, fuliRate?: number): void {
        this.prevResult = EnumBetResult.NotBet;
        if (!waterRate) waterRate = 0.05;
        if (!fuliRate) fuliRate = 0.01;
        if (result == EnumBjlResult.Z) {
            this.zCount++;
        }
        else if (result == EnumBjlResult.X) {
            this.xCount++;
        }
        if (recmV != EnumBjlResult.U) {
            if (result == recmV) {
                this.prevResult = EnumBetResult.Success;
                this.recmResults.push(EnumBetResult.Success);

                this.winCount++;
                this.lwin++;
                this.lfail = 0;
                this.winMoney += recmMoney;

                if (recmV == EnumBjlResult.Z) {
                    this.waterMoney += (recmMoney * waterRate);
                }
            }
            else {
                this.prevResult = EnumBetResult.Fail;
                this.recmResults.push(EnumBetResult.Fail);
                this.failCount++;
                this.lfail++;
                this.lwin = 0;
                this.failMoney += recmMoney;
                this.fuliMoney += (recmMoney * fuliRate);

            }
        }
        else {
            this.prevResult = EnumBetResult.NotBet;
        }
    }

    resetSummaryInfo() {
        this.prevResult = EnumBetResult.NotBet;
        this.zCount = 0;
        this.xCount = 0;
        this.winCount = 0;
        this.failCount = 0;
        this.winMoney = 0;
        this.failMoney = 0;
        this.waterMoney = 0;
        this.fuliMoney = 0;
        this.lwin = 0;
        this.lfail = 0;
        this.recmResults = [];
    }
    addSummaryInfo(addSummary: SummaryInfo) {
        this.zCount += addSummary.zCount;
        this.xCount += addSummary.xCount;
        this.winCount += addSummary.failCount;
        this.failCount += addSummary.failCount;
        this.winMoney += addSummary.winMoney;
        this.failMoney += addSummary.failMoney;
        this.waterMoney += addSummary.waterMoney;
        this.fuliMoney += addSummary.fuliMoney;
        this.lwin = addSummary.lwin;
        this.lfail = addSummary.lfail;
    }
};

export class RecmInfo implements ICopy {
    copyValue(valueObj: any): void {
        let obj = valueObj as RecmInfo;
        if (obj) {
            this.recmV = obj.recmV;
            this.recmMoney = obj.recmMoney;
            this.preResult = obj.preResult;
            this.summaryInfo.copyValue(obj.summaryInfo);
            this.roundSummaryInfo.copyValue(obj.roundSummaryInfo);
            this.betCount = obj.betCount;
            this.preBetCount = obj.preBetCount;
        }
    }
    resetRoundSummaryInfo() {
        this.roundSummaryInfo.resetSummaryInfo();
    }
    recmV: EnumBjlResult = EnumBjlResult.U;
    recmMoney: number = 0;
    preResult: boolean = false;
    summaryInfo: SummaryInfo = new SummaryInfo();
    roundSummaryInfo: SummaryInfo = new SummaryInfo();
    betCount: number = 0;
    preBetCount: number = 0;
}